package my.bcb.servlet;

import com.bcb.dao.*;

import my.bcb.util.TimeUtils;
import com.bcb.model.*;
import com.google.gson.Gson;
import my.bcb.util.PermissionChecker;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.Part;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@MultipartConfig
public class ShareManagementServlet extends HttpServlet {
    
    private ShareDAO shareDAO;
    private ShareLogDAO shareLogDAO;
    private ShareNotificationDAO shareNotificationDAO;
    private EditLockDAO editLockDAO;
    private UserDAO userDAO;
    private UserGroupDAO userGroupDAO;
    private BusinessCardDAO businessCardDAO;
    private CardFolderDAO cardFolderDAO;
    private Gson gson;
    
    @Override
    public void init() throws ServletException {
        try {
            shareDAO = new ShareDAO();
            shareLogDAO = new ShareLogDAO();
            shareNotificationDAO = new ShareNotificationDAO();
            editLockDAO = new EditLockDAO();
            userDAO = new UserDAO();
            userGroupDAO = new UserGroupDAO();
            businessCardDAO = new BusinessCardDAO();
            cardFolderDAO = new CardFolderDAO();
            
            // 🔧 使用TimeUtils配置好的Gson实例
            gson = TimeUtils.createConfiguredGson();
            
            System.out.println("ShareManagementServlet 初始化成功");
        } catch (Exception e) {
            System.err.println("ShareManagementServlet 初始化失败: " + e.getMessage());
            e.printStackTrace();
            throw new ServletException("共享管理Servlet初始化失败", e);
        }
    }
    
    /**
     * 从 multipart/form-data 中读取单个表单字段的值
     */
    private String getValueFromPart(HttpServletRequest req, String partName)
            throws IOException, ServletException {
        try {
            Part part = req.getPart(partName);
            if (part != null) {
                try (InputStream is = part.getInputStream();
                     BufferedReader reader = new BufferedReader(
                             new InputStreamReader(is, StandardCharsets.UTF_8))) {
                    StringBuilder sb = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null) {
                        sb.append(line);
                    }
                    String value = sb.toString();
                    System.out.println("[DEBUG] 读取参数 " + partName + ": " + value);
                    return value.isEmpty() ? null : value;
                }
            }
        } catch (Exception e) {
            System.err.println("[DEBUG] 读取参数 " + partName + " 失败: " + e.getMessage());
            // 如果multipart读取失败，尝试使用传统方式
            String value = req.getParameter(partName);
            System.out.println("[DEBUG] 使用传统方式读取参数 " + partName + ": " + value);
            return value;
        }
        return null;
    }
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        
        // 设置字符编码
        request.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        
        // GET请求通常不是multipart，直接使用getParameter
        String action = request.getParameter("action");
        
        try {
            switch (action != null ? action : "") {
                case "getMyShares":
                    getMyShares(request, response);
                    break;
                case "getAccessibleShares":
                    getAccessibleShares(request, response);
                    break;
                case "getResourceShares":
                    getResourceShares(request, response);
                    break;
                case "getShareableUsers":
                    getShareableUsers(request, response);
                    break;
                case "getShareableGroups":
                    getShareableGroups(request, response);
                    break;
                case "checkEditLock":
                    checkEditLock(request, response);
                    break;
                case "getShareNotifications":
                    getShareNotifications(request, response);
                    break;
                case "getShareLogs":
                    getShareLogs(request, response);
                    break;
                default:
                    sendErrorResponse(response, "不支持的操作类型: " + action);
            }
        } catch (Exception e) {
            System.err.println("处理GET请求失败: " + e.getMessage());
            e.printStackTrace();
            sendErrorResponse(response, "服务器内部错误: " + e.getMessage());
        }
    }
    
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        
        // 设置字符编码
        request.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        
        // POST请求可能是multipart，使用getValueFromPart
        String action = getValueFromPart(request, "action");
        System.out.println("[DEBUG] POST请求action: " + action);
        
        try {
            switch (action != null ? action : "") {
                case "createShare":
                    createShare(request, response);
                    break;
                case "revokeShare":
                    revokeShare(request, response);
                    break;
                case "acquireEditLock":
                    acquireEditLock(request, response);
                    break;
                case "releaseEditLock":
                    releaseEditLock(request, response);
                    break;
                case "markNotificationRead":
                    markNotificationRead(request, response);
                    break;
                case "renewShare":
                    renewShare(request, response);
                    break;

                default:
                    sendErrorResponse(response, "不支持的操作类型: " + action);
            }
        } catch (Exception e) {
            System.err.println("处理POST请求失败: " + e.getMessage());
            e.printStackTrace();
            sendErrorResponse(response, "服务器内部错误: " + e.getMessage());
        }
    }
    
    
    /**
     * 续期共享 - 新增方法
     */
    private void renewShare(HttpServletRequest request, HttpServletResponse response) 
            throws IOException, ServletException {
        try {
            Integer userId = getCurrentUserId(request);
            if (userId == null) {
                System.err.println("[DEBUG] 用户未登录");
                sendErrorResponse(response, "用户未登录");
                return;
            }
            
            String shareIdStr = getValueFromPart(request, "shareId");
            String renewPeriod = getValueFromPart(request, "renewPeriod");
            
            System.out.println(String.format("[DEBUG] 续期共享 - 用户ID: %d, 共享ID: %s, 续期时长: %s", 
                userId, shareIdStr, renewPeriod));
            
            if (shareIdStr == null || renewPeriod == null) {
                System.err.println("[DEBUG] 参数不完整");
                sendErrorResponse(response, "参数不完整");
                return;
            }
            
            int shareId = Integer.parseInt(shareIdStr);
            
            // 验证用户是否有权限续期此共享（必须是共享的创建者）
            if (!verifyShareOwnership(shareId, userId)) {
                System.err.println("[DEBUG] 无权限续期此共享");
                sendErrorResponse(response, "您没有权限续期此共享");
                return;
            }
            
            // 计算新的过期时间
            LocalDateTime newExpiresAt = calculateNewExpirationTime(renewPeriod);
            System.out.println(String.format("[DEBUG] 计算的新过期时间: %s", 
                newExpiresAt != null ? TimeUtils.formatLocalDateTime(newExpiresAt) : "永不过期"));
            
            // 更新共享的过期时间
            boolean success = shareDAO.renewShare(shareId, newExpiresAt);
            System.out.println("[DEBUG] 续期操作结果: " + success);
            
            if (success) {
                // 记录续期日志
                String details = String.format("续期共享，新过期时间: %s", 
                    newExpiresAt != null ? TimeUtils.formatLocalDateTime(newExpiresAt) : "永不过期");
                logShareAction(shareId, userId, ShareLog.Action.UPDATE, details, getClientIP(request));
                
                Map<String, Object> result = new HashMap<>();
                result.put("success", true);
                result.put("message", "共享续期成功");
                result.put("newExpiresAt", newExpiresAt != null ? TimeUtils.formatLocalDateTime(newExpiresAt) : null);
                sendJsonResponse(response, result);
            } else {
                System.err.println("[DEBUG] 数据库更新失败");
                sendErrorResponse(response, "续期共享失败");
            }
            
        } catch (NumberFormatException e) {
            System.err.println("[DEBUG] 数字格式错误: " + e.getMessage());
            sendErrorResponse(response, "参数格式错误");
        } catch (Exception e) {
            System.err.println(String.format("[DEBUG] 续期共享异常: %s", e.getMessage()));
            e.printStackTrace();
            sendErrorResponse(response, String.format("续期共享失败: %s", e.getMessage()));
        }
    }
    
    
    /**
     * 验证共享所有权
     */
    private boolean verifyShareOwnership(int shareId, int userId) {
        try {
            Share share = shareDAO.getShareById(shareId);
            if (share != null) {
                boolean isOwner = share.getOwnerId() == userId;
                System.out.println(String.format("[DEBUG] 共享所有权验证 - shareId: %d, ownerId: %d, currentUserId: %d, isOwner: %b", 
                    shareId, share.getOwnerId(), userId, isOwner));
                return isOwner;
            }
            System.err.println("[DEBUG] 共享记录不存在: " + shareId);
            return false;
        } catch (Exception e) {
            System.err.println("[DEBUG] 验证共享所有权异常: " + e.getMessage());
            e.printStackTrace();
            return false;
        }
    }

    
    /**
     * 计算新的过期时间
     */
    private LocalDateTime calculateNewExpirationTime(String renewPeriod) {
        LocalDateTime now = LocalDateTime.now();
        
        System.out.println(String.format("[DEBUG] 计算续期时间 - 当前时间: %s, 续期类型: %s", 
            TimeUtils.formatLocalDateTime(now), renewPeriod));
        
        LocalDateTime result;
        switch (renewPeriod) {
            case "1hour":
                result = now.plusHours(1);
                break;
            case "1day":
                result = now.plusDays(1);
                break;
            case "1week":
                result = now.plusWeeks(1);
                break;
            case "1month":
                result = now.plusMonths(1);
                break;
            case "never":
                result = null; // 永不过期
                break;
            default:
                System.err.println("[DEBUG] 未知的续期类型: " + renewPeriod);
                result = now.plusDays(1); // 默认延长1天
        }
        
        String resultStr = result != null ? TimeUtils.formatLocalDateTime(result) : "永不过期";
        System.out.println(String.format("[DEBUG] 续期计算结果 - 新过期时间: %s", resultStr));
        
        return result;
    }
    
    
    /**
     * 创建共享 - 防重复版本
     */
    private void createShare(HttpServletRequest request, HttpServletResponse response) 
            throws IOException, ServletException {
        try {
            Integer userId = getCurrentUserId(request);
            if (userId == null) {
                System.err.println("[DEBUG] 用户未登录");
                sendErrorResponse(response, "用户未登录");
                return;
            }
            
            String currentTimeStr = TimeUtils.formatLocalDateTime(LocalDateTime.now());
            System.out.println(String.format("[DEBUG] 创建共享 - 用户ID: %d, 当前时间: %s", 
                userId, currentTimeStr));
            
            // 获取参数（这部分代码保持原样）
            String resourceType = getValueFromPart(request, "resourceType");
            String resourceIdStr = getValueFromPart(request, "resourceId");
            String shareType = getValueFromPart(request, "shareType");
            String targetIdStr = getValueFromPart(request, "targetId");
            String permissionLevel = getValueFromPart(request, "permissionLevel");
            String expiresInStr = getValueFromPart(request, "expiresIn");
            
            System.out.println("[DEBUG] 接收到的参数:");
            System.out.println("resourceType: " + resourceType);
            System.out.println("resourceId: " + resourceIdStr);
            System.out.println("shareType: " + shareType);
            System.out.println("targetId: " + targetIdStr);
            System.out.println("permissionLevel: " + permissionLevel);
            System.out.println("expiresIn: " + expiresInStr);
            
            // 参数验证
            if (resourceType == null || resourceIdStr == null || shareType == null || permissionLevel == null) {
                System.err.println("[DEBUG] 参数不完整");
                sendErrorResponse(response, "参数不完整");
                return;
            }
            
            int resourceId = Integer.parseInt(resourceIdStr);
            Share.ResourceType type = Share.ResourceType.valueOf(resourceType.toUpperCase());
            Share.ShareType sType = Share.ShareType.valueOf(shareType.toUpperCase());
            Share.PermissionLevel pLevel = Share.PermissionLevel.valueOf(permissionLevel.toUpperCase());
            
            // 验证资源拥有权
            System.out.println("[DEBUG] 开始验证资源拥有权");
            if (!verifyResourceOwnership(userId, type, resourceId)) {
                System.err.println("[DEBUG] 资源拥有权验证失败");
                sendErrorResponse(response, "你不能共享不属于自己的资源");
                return;
            }
            System.out.println("[DEBUG] 资源拥有权验证通过");
            
            // 检查重复共享
            String duplicateCheckResult = checkForDuplicateShareEnhanced(userId, type, resourceId, sType, targetIdStr);
            if (duplicateCheckResult != null) {
                System.out.println("[DEBUG] 发现重复共享: " + duplicateCheckResult);
                Map<String, Object> result = new HashMap<>();
                result.put("success", true);
                result.put("message", duplicateCheckResult);
                result.put("isDuplicate", true);
                sendJsonResponse(response, result);
                return;
            }
            
            // 创建共享对象
            Share share = new Share();
            share.setOwnerId(userId);
            share.setResourceType(type);
            share.setResourceId(resourceId);
            share.setShareType(sType);
            share.setPermissionLevel(pLevel);
            
            // 设置目标ID
            if (sType != Share.ShareType.PUBLIC && targetIdStr != null && !targetIdStr.trim().isEmpty()) {
                share.setTargetId(Integer.parseInt(targetIdStr));
            }
            
            // 设置过期时间
            if (expiresInStr != null && !expiresInStr.trim().isEmpty()) {
                LocalDateTime expiresAt = calculateExpirationTime(expiresInStr);
                share.setExpiresAt(expiresAt);
            }
            
            // 设置资源名称
            String resourceName = getResourceName(type, resourceId);
            share.setResourceName(resourceName);
            System.out.println("[DEBUG] 资源名称: " + resourceName);
            
            String expiresStr = share.getExpiresAt() != null ? 
                TimeUtils.formatLocalDateTime(share.getExpiresAt()) : "永不过期";
            System.out.println(String.format("[DEBUG] 创建的共享对象: 资源=%s, 过期时间=%s", 
                resourceName, expiresStr));
            
            // 创建共享
            boolean success = createShareWithTransactionCheck(share);
            System.out.println("[DEBUG] 创建共享结果: " + success);
            
            if (success) {
                // 记录日志
                String details = String.format("创建共享: %s (%s:%s)", 
                    resourceName, shareType, permissionLevel);
                logShareAction(share.getShareId(), userId, ShareLog.Action.CREATE, details, getClientIP(request));
                
                // 发送通知
                if (sType != Share.ShareType.PUBLIC) {
                    sendShareNotifications(share, resourceName);
                }
                
                Map<String, Object> result = new HashMap<>();
                result.put("success", true);
                result.put("message", "共享创建成功");
                result.put("shareId", share.getShareId());
                sendJsonResponse(response, result);
            } else {
                System.err.println("[DEBUG] 数据库操作失败");
                sendErrorResponse(response, "创建共享失败");
            }
            
        } catch (NumberFormatException e) {
            System.err.println("[DEBUG] 数字格式错误: " + e.getMessage());
            sendErrorResponse(response, "参数格式错误");
        } catch (Exception e) {
            System.err.println(String.format("[DEBUG] 创建共享异常: %s", e.getMessage()));
            e.printStackTrace();
            sendErrorResponse(response, String.format("创建共享失败: %s", e.getMessage()));
        }
    }
    
    
    

/**
 * 在事务中创建共享，并进行最后的重复检查
 */
private boolean createShareWithTransactionCheck(Share share) {
    Connection conn = null;
    try {
        conn = my.bcb.util.DBConnection.getConnection();
        conn.setAutoCommit(false); // 开启事务
        
        // 在事务中再次检查重复（防止并发问题）
        String checkSql = "SELECT COUNT(*) FROM shares WHERE " +
                         "owner_id = ? AND resource_type = ? AND resource_id = ? AND " +
                         "share_type = ? AND is_active = TRUE";
        
        List<Object> checkParams = new ArrayList<>();
        checkParams.add(share.getOwnerId());
        checkParams.add(share.getResourceType().name().toLowerCase());
        checkParams.add(share.getResourceId());
        checkParams.add(share.getShareType().name().toLowerCase());
        
        if (share.getShareType() != Share.ShareType.PUBLIC && share.getTargetId() != null) {
            checkSql += " AND target_id = ?";
            checkParams.add(share.getTargetId());
        } else if (share.getShareType() != Share.ShareType.PUBLIC) {
            checkSql += " AND target_id IS NULL";
        }
        
        try (PreparedStatement checkStmt = conn.prepareStatement(checkSql)) {
            for (int i = 0; i < checkParams.size(); i++) {
                checkStmt.setObject(i + 1, checkParams.get(i));
            }
            
            ResultSet rs = checkStmt.executeQuery();
            if (rs.next() && rs.getInt(1) > 0) {
                System.out.println("[DEBUG] 事务中发现重复记录，取消创建");
                conn.rollback();
                return true; // 虽然没有创建新记录，但返回true表示"成功"（因为已存在）
            }
        }
        
        // 没有重复，执行插入
        boolean result = shareDAO.createShareInTransaction(conn, share);
        
        if (result) {
            conn.commit();
            System.out.println("[DEBUG] 事务提交成功");
        } else {
            conn.rollback();
            System.out.println("[DEBUG] 创建失败，事务回滚");
        }
        
        return result;
        
    } catch (Exception e) {
        System.err.println("[DEBUG] 事务执行异常: " + e.getMessage());
        e.printStackTrace();
        try {
            if (conn != null) {
                conn.rollback();
            }
        } catch (Exception rollbackEx) {
            System.err.println("[DEBUG] 事务回滚失败: " + rollbackEx.getMessage());
        }
        return false;
    } finally {
        try {
            if (conn != null) {
                conn.setAutoCommit(true);
                conn.close();
            }
        } catch (Exception closeEx) {
            System.err.println("[DEBUG] 关闭连接失败: " + closeEx.getMessage());
        }
    }
}
    	
    /**
     * 加强的重复检查机制
     */
    private String checkForDuplicateShareEnhanced(int ownerId, Share.ResourceType resourceType, 
                                               int resourceId, Share.ShareType shareType, String targetIdStr) {
        try {
            // 构建查询条件
            String sql = "SELECT share_id, resource_name, created_at FROM shares WHERE " +
                        "owner_id = ? AND resource_type = ? AND resource_id = ? AND " +
                        "share_type = ? AND is_active = TRUE";
            
            List<Object> params = new ArrayList<>();
            params.add(ownerId);
            params.add(resourceType.name().toLowerCase());
            params.add(resourceId);
            params.add(shareType.name().toLowerCase());
            
            // 如果有目标ID，也要检查
            if (shareType != Share.ShareType.PUBLIC && targetIdStr != null && !targetIdStr.trim().isEmpty()) {
                sql += " AND target_id = ?";
                params.add(Integer.parseInt(targetIdStr));
            } else if (shareType != Share.ShareType.PUBLIC) {
                sql += " AND target_id IS NULL";
            }
            
            // 添加时间窗口检查（防止短时间内的重复请求）
            sql += " AND created_at > DATE_SUB(NOW(), INTERVAL 10 SECOND)";
            
            // 执行查询
            try (Connection conn = my.bcb.util.DBConnection.getConnection();
                 PreparedStatement stmt = conn.prepareStatement(sql)) {
                
                for (int i = 0; i < params.size(); i++) {
                    stmt.setObject(i + 1, params.get(i));
                }
                
                ResultSet rs = stmt.executeQuery();
                if (rs.next()) {
                    String resourceName = rs.getString("resource_name");
                    String createdAt = rs.getString("created_at");
                    int existingShareId = rs.getInt("share_id");
                    
                    System.out.println("[DEBUG] 找到重复共享记录: ID=" + existingShareId + 
                                     ", 资源=" + resourceName + ", 创建时间=" + createdAt);
                    
                    return "共享已存在，无需重复创建（资源: " + resourceName + "）";
                }
            }
            
            // 如果没有找到完全重复的，检查是否有类似的共享（不同目标但相同资源）
            String similarSql = "SELECT COUNT(*) FROM shares WHERE " +
                              "owner_id = ? AND resource_type = ? AND resource_id = ? AND " +
                              "is_active = TRUE";
            
            try (Connection conn = my.bcb.util.DBConnection.getConnection();
                 PreparedStatement stmt = conn.prepareStatement(similarSql)) {
                
                stmt.setInt(1, ownerId);
                stmt.setString(2, resourceType.name().toLowerCase());
                stmt.setInt(3, resourceId);
                
                ResultSet rs = stmt.executeQuery();
                if (rs.next()) {
                    int count = rs.getInt(1);
                    System.out.println("[DEBUG] 找到 " + count + " 个相似的共享记录");
                    
                    if (count >= 10) { // 如果同一资源的共享数量过多，可能是异常
                        return "该资源的共享数量已达上限，请检查是否重复操作";
                    }
                }
            }
            
        } catch (Exception e) {
            System.err.println("[DEBUG] 检查重复共享时出错: " + e.getMessage());
            e.printStackTrace();
            // 出错时为了安全起见，假设可能重复
            return "系统检查异常，可能存在重复共享";
        }
        
        return null; // 没有发现重复
    }
    
    
    
    /**
     * 撤销共享
     */
    private void revokeShare(HttpServletRequest request, HttpServletResponse response) 
            throws IOException, ServletException {
        try {
            Integer userId = getCurrentUserId(request);
            if (userId == null) {
                sendErrorResponse(response, "用户未登录");
                return;
            }
            
            String shareIdStr = getValueFromPart(request, "shareId");
            if (shareIdStr == null) {
                sendErrorResponse(response, "共享ID不能为空");
                return;
            }
            
            int shareId = Integer.parseInt(shareIdStr);
            
            boolean success = shareDAO.revokeShare(shareId, userId);
            
            if (success) {
                // 记录日志
                logShareAction(shareId, userId, ShareLog.Action.REVOKE, "撤销共享", getClientIP(request));
                
                Map<String, Object> result = new HashMap<>();
                result.put("success", true);
                result.put("message", "共享已撤销");
                sendJsonResponse(response, result);
            } else {
                sendErrorResponse(response, "撤销共享失败");
            }
            
        } catch (NumberFormatException e) {
            sendErrorResponse(response, "参数格式错误");
        } catch (Exception e) {
            System.err.println("撤销共享失败: " + e.getMessage());
            e.printStackTrace();
            sendErrorResponse(response, "撤销共享失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取编辑锁定
     */
    private void acquireEditLock(HttpServletRequest request, HttpServletResponse response) 
            throws IOException, ServletException {
        try {
            Integer userId = getCurrentUserId(request);
            if (userId == null) {
                sendErrorResponse(response, "用户未登录");
                return;
            }
            
            String resourceType = getValueFromPart(request, "resourceType");
            String resourceIdStr = getValueFromPart(request, "resourceId");
            
            if (resourceType == null || resourceIdStr == null) {
                sendErrorResponse(response, "参数不完整");
                return;
            }
            
            Share.ResourceType type = Share.ResourceType.valueOf(resourceType.toUpperCase());
            int resourceId = Integer.parseInt(resourceIdStr);
            
            // 检查现有锁定
            EditLock existingLock = editLockDAO.getLock(type, resourceId);
            if (existingLock != null && !existingLock.isExpired() && existingLock.getUserId() != userId) {
                sendErrorResponse(response, "资源正在被用户 \"" + existingLock.getUsername() + "\" 编辑");
                return;
            }
            
            // 获取用户信息
            User user = userDAO.findById(userId);
            if (user == null) {
                sendErrorResponse(response, "用户信息不存在");
                return;
            }
            
            // 创建新锁定（15分钟有效期）
            LocalDateTime expiresAt = LocalDateTime.now().plusMinutes(15);
            EditLock lock = new EditLock(type, resourceId, userId, user.getUsername(), expiresAt);
            
            boolean success = editLockDAO.createLock(lock);
            
            if (success) {
                Map<String, Object> result = new HashMap<>();
                result.put("success", true);
                result.put("message", "获取编辑锁定成功");
                result.put("expiresAt", expiresAt.toString());
                sendJsonResponse(response, result);
            } else {
                sendErrorResponse(response, "获取编辑锁定失败");
            }
            
        } catch (Exception e) {
            System.err.println("获取编辑锁定失败: " + e.getMessage());
            e.printStackTrace();
            sendErrorResponse(response, "获取编辑锁定失败: " + e.getMessage());
        }
    }
    
    /**
     * 释放编辑锁定
     */
    private void releaseEditLock(HttpServletRequest request, HttpServletResponse response) 
            throws IOException, ServletException {
        try {
            Integer userId = getCurrentUserId(request);
            if (userId == null) {
                sendErrorResponse(response, "用户未登录");
                return;
            }
            
            String resourceType = getValueFromPart(request, "resourceType");
            String resourceIdStr = getValueFromPart(request, "resourceId");
            
            if (resourceType == null || resourceIdStr == null) {
                sendErrorResponse(response, "参数不完整");
                return;
            }
            
            Share.ResourceType type = Share.ResourceType.valueOf(resourceType.toUpperCase());
            int resourceId = Integer.parseInt(resourceIdStr);
            
            boolean success = editLockDAO.releaseLock(type, resourceId, userId);
            
            Map<String, Object> result = new HashMap<>();
            result.put("success", success);
            result.put("message", success ? "编辑锁定已释放" : "释放编辑锁定失败");
            
            sendJsonResponse(response, result);
            
        } catch (Exception e) {
            System.err.println("释放编辑锁定失败: " + e.getMessage());
            e.printStackTrace();
            sendErrorResponse(response, "释放编辑锁定失败: " + e.getMessage());
        }
    }
    
    /**
     * 标记通知为已读
     */
    private void markNotificationRead(HttpServletRequest request, HttpServletResponse response) 
            throws IOException, ServletException {
        try {
            Integer userId = getCurrentUserId(request);
            if (userId == null) {
                sendErrorResponse(response, "用户未登录");
                return;
            }
            
            String notificationIdStr = getValueFromPart(request, "notificationId");
            if (notificationIdStr == null) {
                sendErrorResponse(response, "通知ID不能为空");
                return;
            }
            
            int notificationId = Integer.parseInt(notificationIdStr);
            
            boolean success = shareNotificationDAO.markAsRead(notificationId, userId);
            
            Map<String, Object> result = new HashMap<>();
            result.put("success", success);
            result.put("message", success ? "通知已标记为已读" : "标记通知失败");
            
            sendJsonResponse(response, result);
            
        } catch (Exception e) {
            System.err.println("标记通知已读失败: " + e.getMessage());
            e.printStackTrace();
            sendErrorResponse(response, "标记通知已读失败: " + e.getMessage());
        }
    }
    
    // 以下方法保持不变，因为它们是GET请求
    
    /**
     * 获取我的共享列表
     */
    private void getMyShares(HttpServletRequest request, HttpServletResponse response) 
            throws IOException {
        try {
            Integer userId = getCurrentUserId(request);
            if (userId == null) {
                sendErrorResponse(response, "用户未登录");
                return;
            }
            
            System.out.println(String.format("[DEBUG] getMyShares - 当前用户ID: %d", userId));
            
            List<Share> shares = shareDAO.getSharesByOwner(userId);
            
            System.out.println(String.format("[DEBUG] 查询到的共享数量: %d", shares.size()));
            
            // 添加详细的调试信息
            for (int i = 0; i < shares.size(); i++) {
                Share share = shares.get(i);
                System.out.println(String.format("[DEBUG] 共享详情 %d:", i + 1));
                System.out.println(String.format("  ID: %d", share.getShareId()));
                System.out.println(String.format("  资源名: %s", share.getResourceName()));
                
                String expiresStr = share.getExpiresAt() != null ? 
                    TimeUtils.formatLocalDateTime(share.getExpiresAt()) : "永不过期";
                System.out.println(String.format("  过期时间: %s", expiresStr));
                
                String createdStr = share.getCreatedAt() != null ? 
                    TimeUtils.formatLocalDateTime(share.getCreatedAt()) : "未知";
                System.out.println(String.format("  创建时间: %s", createdStr));
                
                System.out.println(String.format("  目标ID: %s", share.getTargetId()));
                System.out.println(String.format("  目标名称: %s", share.getTargetName()));
            }
            
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("shares", shares);
            result.put("message", "获取共享列表成功");
            
            sendJsonResponse(response, result);
            
        } catch (Exception e) {
            System.err.println(String.format("获取共享列表失败: %s", e.getMessage()));
            e.printStackTrace();
            sendErrorResponse(response, String.format("获取共享列表失败: %s", e.getMessage()));
        }
    }

    
    /**
     * 获取可访问的共享资源
     */
    private void getAccessibleShares(HttpServletRequest request, HttpServletResponse response) 
            throws IOException {
        try {
            Integer userId = getCurrentUserId(request);
            System.out.println("[DEBUG] getAccessibleShares - 当前用户ID: " + userId);
            
            if (userId == null) {
                System.err.println("[DEBUG] 用户未登录");
                sendErrorResponse(response, "用户未登录");
                return;
            }
            
            List<Share> shares = shareDAO.getAccessibleShares(userId);
            System.out.println("[DEBUG] DAO返回的共享数量: " + shares.size());
            
            for (int i = 0; i < shares.size(); i++) {
                Share share = shares.get(i);
                System.out.println("[DEBUG] 共享 " + (i+1) + ": ID=" + share.getShareId() + 
                                 ", 资源=" + share.getResourceName() + 
                                 ", 类型=" + share.getShareType() +
                                 ", 所有者=" + share.getOwnerName());
            }
            
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("shares", shares);
            result.put("message", "获取可访问共享成功");
            
            System.out.println("[DEBUG] 准备返回的结果: " + result);
            
            sendJsonResponse(response, result);
            
        } catch (Exception e) {
            System.err.println("[ERROR] 获取可访问共享失败: " + e.getMessage());
            e.printStackTrace();
            sendErrorResponse(response, "获取可访问共享失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取可共享的用户列表
     */
    private void getShareableUsers(HttpServletRequest request, HttpServletResponse response) 
            throws IOException {
        try {
            Integer userId = getCurrentUserId(request);
            if (userId == null) {
                sendErrorResponse(response, "用户未登录");
                return;
            }
            
            List<User> users = userDAO.findAll();
            List<Map<String, Object>> shareableUsers = new ArrayList<>();
            
            for (User user : users) {
                if (user.getUserId() != userId) {  // 排除自己
                    Map<String, Object> userInfo = new HashMap<>();
                    userInfo.put("userId", user.getUserId());
                    userInfo.put("username", user.getUsername());
                    userInfo.put("email", user.getEmail());
                    shareableUsers.add(userInfo);
                }
            }
            
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("users", shareableUsers);
            result.put("message", "获取用户列表成功");
            
            sendJsonResponse(response, result);
            
        } catch (Exception e) {
            System.err.println("获取用户列表失败: " + e.getMessage());
            e.printStackTrace();
            sendErrorResponse(response, "获取用户列表失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取可共享的用户组列表
     */
    private void getShareableGroups(HttpServletRequest request, HttpServletResponse response) 
            throws IOException {
        try {
            List<UserGroup> groups = userGroupDAO.findAll();
            List<Map<String, Object>> shareableGroups = new ArrayList<>();
            
            for (UserGroup group : groups) {
                Map<String, Object> groupInfo = new HashMap<>();
                groupInfo.put("groupId", group.getGroupId());
                groupInfo.put("groupName", group.getGroupName());
                groupInfo.put("description", group.getGroupDescription());
                shareableGroups.add(groupInfo);
            }
            
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("groups", shareableGroups);
            result.put("message", "获取用户组列表成功");
            
            sendJsonResponse(response, result);
            
        } catch (Exception e) {
            System.err.println("获取用户组列表失败: " + e.getMessage());
            e.printStackTrace();
            sendErrorResponse(response, "获取用户组列表失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取编辑锁定状态
     */
    private void checkEditLock(HttpServletRequest request, HttpServletResponse response) 
            throws IOException {
        try {
            String resourceType = request.getParameter("resourceType");
            String resourceIdStr = request.getParameter("resourceId");
            
            if (resourceType == null || resourceIdStr == null) {
                sendErrorResponse(response, "参数不完整");
                return;
            }
            
            Share.ResourceType type = Share.ResourceType.valueOf(resourceType.toUpperCase());
            int resourceId = Integer.parseInt(resourceIdStr);
            
            EditLock lock = editLockDAO.getLock(type, resourceId);
            
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            
            if (lock != null && !lock.isExpired()) {
                result.put("locked", true);
                result.put("lockedBy", lock.getUsername());
                result.put("lockedAt", lock.getCreatedAt().toString());
                result.put("expiresAt", lock.getExpiresAt().toString());
            } else {
                result.put("locked", false);
                // 清理过期锁定
                if (lock != null && lock.isExpired()) {
                    editLockDAO.releaseLock(type, resourceId, lock.getUserId());
                }
            }
            
            sendJsonResponse(response, result);
            
        } catch (Exception e) {
            System.err.println("检查编辑锁定失败: " + e.getMessage());
            e.printStackTrace();
            sendErrorResponse(response, "检查编辑锁定失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取资源的共享记录
     */
    private void getResourceShares(HttpServletRequest request, HttpServletResponse response) 
            throws IOException {
        try {
            String resourceType = request.getParameter("resourceType");
            String resourceIdStr = request.getParameter("resourceId");
            
            if (resourceType == null || resourceIdStr == null) {
                sendErrorResponse(response, "参数不完整");
                return;
            }
            
            Share.ResourceType type = Share.ResourceType.valueOf(resourceType.toUpperCase());
            int resourceId = Integer.parseInt(resourceIdStr);
            
            List<Share> shares = shareDAO.getResourceShares(type, resourceId);
            
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("shares", shares);
            result.put("message", "获取资源共享记录成功");
            
            sendJsonResponse(response, result);
            
        } catch (Exception e) {
            System.err.println("获取资源共享记录失败: " + e.getMessage());
            e.printStackTrace();
            sendErrorResponse(response, "获取资源共享记录失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取共享日志
     */
    private void getShareLogs(HttpServletRequest request, HttpServletResponse response) 
            throws IOException {
        try {
            String shareIdStr = request.getParameter("shareId");
            if (shareIdStr == null) {
                sendErrorResponse(response, "共享ID不能为空");
                return;
            }
            
            int shareId = Integer.parseInt(shareIdStr);
            
            List<ShareLog> logs = shareLogDAO.getShareLogs(shareId);
            
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("logs", logs);
            result.put("message", "获取共享日志成功");
            
            sendJsonResponse(response, result);
            
        } catch (Exception e) {
            System.err.println("获取共享日志失败: " + e.getMessage());
            e.printStackTrace();
            sendErrorResponse(response, "获取共享日志失败: " + e.getMessage());
        }
    }
    

    /**
     * 获取共享通知 - 修复版：使用有效通知计数
     */
    private void getShareNotifications(HttpServletRequest request, HttpServletResponse response) 
            throws IOException {
        try {
            Integer userId = getCurrentUserId(request);
            if (userId == null) {
                sendErrorResponse(response, "用户未登录");
                return;
            }
            
            List<ShareNotification> notifications = shareNotificationDAO.getUnreadNotifications(userId);
            int validCount = shareNotificationDAO.getValidNotificationCount(userId);
            
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("notifications", notifications);
            result.put("count", validCount);  // 使用有效计数
            result.put("message", "获取通知成功");
            
            sendJsonResponse(response, result);
            
        } catch (Exception e) {
            System.err.println("获取共享通知失败: " + e.getMessage());
            e.printStackTrace();
            sendErrorResponse(response, "获取共享通知失败: " + e.getMessage());
        }
    }
    // 辅助方法
    private Integer getCurrentUserId(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        if (session != null) {
            return (Integer) session.getAttribute("userId");
        }
        return null;
    }
    
    /**
     * 修复：增强的资源所有权验证
     */
    private boolean verifyResourceOwnership(int userId, Share.ResourceType type, int resourceId) {
        try {
            System.out.println("[DEBUG] 验证资源所有权 - 用户ID: " + userId + ", 类型: " + type + ", 资源ID: " + resourceId);
            
            if (type == Share.ResourceType.CARD) {
                BusinessCard card = businessCardDAO.findById(resourceId);
                System.out.println("[DEBUG] 查找到的名片: " + (card != null ? card.getName() : "null"));
                
                if (card != null) {
                    int folderId;
                    try {
                        folderId = card.getFolderId();
                    } catch (Exception e1) {
                        try {
                            java.lang.reflect.Method method = card.getClass().getMethod("getFolder_id");
                            folderId = (Integer) method.invoke(card);
                        } catch (Exception e2) {
                            System.err.println("[DEBUG] 无法获取名片的文件夹ID: " + e2.getMessage());
                            return false;
                        }
                    }
                    
                    System.out.println("[DEBUG] 名片所在文件夹ID: " + folderId);
                    CardFolder folder = cardFolderDAO.findById(folderId);
                    System.out.println("[DEBUG] 查找到的文件夹: " + (folder != null ? folder.getFolderName() : "null"));
                    
                    if (folder != null) {
                        int folderUserId;
                        try {
                            folderUserId = folder.getUserId();
                        } catch (Exception e1) {
                            try {
                                java.lang.reflect.Method method = folder.getClass().getMethod("getUser_id");
                                folderUserId = (Integer) method.invoke(folder);
                            } catch (Exception e2) {
                                System.err.println("[DEBUG] 无法获取文件夹的用户ID: " + e2.getMessage());
                                return false;
                            }
                        }
                        
                        System.out.println("[DEBUG] 文件夹所有者ID: " + folderUserId + ", 当前用户ID: " + userId);
                        return folderUserId == userId;
                    }
                }
            } else {
                CardFolder folder = cardFolderDAO.findById(resourceId);
                System.out.println("[DEBUG] 查找到的文件夹: " + (folder != null ? folder.getFolderName() : "null"));
                
                if (folder != null) {
                    int folderUserId;
                    try {
                        folderUserId = folder.getUserId();
                    } catch (Exception e1) {
                        try {
                            java.lang.reflect.Method method = folder.getClass().getMethod("getUser_id");
                            folderUserId = (Integer) method.invoke(folder);
                        } catch (Exception e2) {
                            System.err.println("[DEBUG] 无法获取文件夹的用户ID: " + e2.getMessage());
                            return false;
                        }
                    }
                    
                    System.out.println("[DEBUG] 文件夹所有者ID: " + folderUserId + ", 当前用户ID: " + userId);
                    return folderUserId == userId;
                }
            }
        } catch (Exception e) {
            System.err.println("[DEBUG] 验证资源所有权异常: " + e.getMessage());
            e.printStackTrace();
        }
        return false;
    }
    
    private String getResourceName(Share.ResourceType type, int resourceId) {
        try {
            if (type == Share.ResourceType.CARD) {
                BusinessCard card = businessCardDAO.findById(resourceId);
                if (card != null) {
                    try {
                        return card.getName();
                    } catch (Exception e1) {
                        try {
                            java.lang.reflect.Method method = card.getClass().getMethod("getCardName");
                            return (String) method.invoke(card);
                        } catch (Exception e2) {
                            System.err.println("[DEBUG] 无法获取名片名称: " + e2.getMessage());
                            return "未知名片";
                        }
                    }
                }
            } else {
                CardFolder folder = cardFolderDAO.findById(resourceId);
                if (folder != null) {
                    try {
                        return folder.getFolderName();
                    } catch (Exception e1) {
                        try {
                            java.lang.reflect.Method method = folder.getClass().getMethod("getFolder_name");
                            return (String) method.invoke(folder);
                        } catch (Exception e2) {
                            System.err.println("[DEBUG] 无法获取文件夹名称: " + e2.getMessage());
                            return "未知文件夹";
                        }
                    }
                }
            }
        } catch (Exception e) {
            System.err.println("[DEBUG] 获取资源名称异常: " + e.getMessage());
            e.printStackTrace();
        }
        return "未知资源";
    }
    
    private LocalDateTime calculateExpirationTime(String expiresIn) {
        LocalDateTime now = LocalDateTime.now();
        
        System.out.println(String.format("[DEBUG] 计算过期时间 - 当前时间: %s, 输入: %s", 
            TimeUtils.formatLocalDateTime(now), expiresIn));
        
        LocalDateTime result;
        switch (expiresIn) {
            case "1hour":
                result = now.plusHours(1);
                break;
            case "1day":
                result = now.plusDays(1);
                break;
            case "1week":
                result = now.plusWeeks(1);
                break;
            case "1month":
                result = now.plusMonths(1);
                break;
            default:
                result = null; // 永不过期
        }
        
        String resultStr = result != null ? TimeUtils.formatLocalDateTime(result) : "永不过期";
        System.out.println(String.format("[DEBUG] 计算结果 - 过期时间: %s", resultStr));
        
        return result;
    }

    
    private void logShareAction(int shareId, int userId, ShareLog.Action action, String details, String ipAddress) {
        try {
            ShareLog log = new ShareLog(shareId, userId, action, details, ipAddress);
            shareLogDAO.logAction(log);
        } catch (Exception e) {
            System.err.println("记录共享日志失败: " + e.getMessage());
        }
    }
    
    private void sendShareNotifications(Share share, String resourceName) {
        try {
            String message = "用户分享了" + (share.getResourceType() == Share.ResourceType.CARD ? "名片" : "名片夹") + ": " + resourceName;
            
            if (share.getShareType() == Share.ShareType.USER && share.getTargetId() != null) {
                ShareNotification notification = new ShareNotification(share.getShareId(), share.getTargetId(), message);
                shareNotificationDAO.createNotification(notification);
            } else if (share.getShareType() == Share.ShareType.GROUP && share.getTargetId() != null) {
                // 获取组内所有用户并发送通知
                try {
                    UserGroupMappingDAO userGroupMappingDAO = new UserGroupMappingDAO();
                    List<Integer> groupUserIds = userGroupMappingDAO.getUsersByGroup(share.getTargetId());
                    
                    // 排除分享者自己
                    List<Integer> targetUserIds = new ArrayList<>();
                    for (Integer userId : groupUserIds) {
                        if (!userId.equals(share.getOwnerId())) {
                            targetUserIds.add(userId);
                        }
                    }
                    
                    if (!targetUserIds.isEmpty()) {
                        shareNotificationDAO.createNotificationsForUsers(share.getShareId(), targetUserIds, message);
                    }
                } catch (Exception e) {
                    System.err.println("为用户组发送通知失败: " + e.getMessage());
                }
            }
        } catch (Exception e) {
            System.err.println("发送共享通知失败: " + e.getMessage());
        }
    }
    
    /**
     * 继承共享权限（用于名片夹内新增名片时）
     */
    public void inheritFolderSharePermissions(int folderId, int newCardId) {
        try {
            // 获取名片夹的所有共享记录
            List<Share> folderShares = shareDAO.getResourceShares(Share.ResourceType.FOLDER, folderId);
            
            // 获取名片信息
            BusinessCard card = businessCardDAO.findById(newCardId);
            if (card == null) {
                return;
            }
            
            // 为每个共享创建对应的名片共享
            for (Share folderShare : folderShares) {
                if (folderShare.isActive() && !folderShare.isExpired()) {
                    Share cardShare = new Share();
                    cardShare.setOwnerId(folderShare.getOwnerId());
                    cardShare.setResourceType(Share.ResourceType.CARD);
                    cardShare.setResourceId(newCardId);
                    cardShare.setShareType(folderShare.getShareType());
                    cardShare.setTargetId(folderShare.getTargetId());
                    cardShare.setPermissionLevel(folderShare.getPermissionLevel());
                    cardShare.setExpiresAt(folderShare.getExpiresAt());
                    cardShare.setResourceName(card.getName());
                    
                    shareDAO.createShare(cardShare);
                    
                    // 记录继承日志
                    String details = "继承名片夹共享权限: " + card.getName() + " (来自名片夹 " + folderId + ")";
                    logShareAction(cardShare.getShareId(), folderShare.getOwnerId(), ShareLog.Action.CREATE, details, "system");
                }
            }
        } catch (Exception e) {
            System.err.println("继承共享权限失败: " + e.getMessage());
        }
    }
    

	/**
	 * 检查用户对资源的访问权限
	 */
	public boolean checkResourceAccess(int userId, Share.ResourceType resourceType, int resourceId, Share.PermissionLevel requiredPermission) {
	    try {
	        // 首先检查是否为资源所有者
	        if (verifyResourceOwnership(userId, resourceType, resourceId)) {
	            return true;
	        }
	        
	        // 检查共享权限
	        Share sharePermission = shareDAO.getUserSharePermission(userId, resourceType, resourceId);
	        if (sharePermission != null && sharePermission.isActive() && !sharePermission.isExpired()) {
	            // 如果只需要读权限,任何共享权限都可以
	            if (requiredPermission == Share.PermissionLevel.READ) {  // 修正：read -> READ
	                return true;
	            }
	            // 如果需要编辑权限,必须具有编辑权限
	            return sharePermission.getPermissionLevel() == Share.PermissionLevel.EDIT;
	        }
	        
	        return false;
	    } catch (Exception e) {
	        System.err.println("检查资源访问权限失败: " + e.getMessage());
	        return false;
	    }
	}
    
    private String getClientIP(HttpServletRequest request) {
        String xForwardedFor = request.getHeader("X-Forwarded-For");
        if (xForwardedFor != null && !xForwardedFor.isEmpty()) {
            return xForwardedFor.split(",")[0];
        }
        
        String xRealIP = request.getHeader("X-Real-IP");
        if (xRealIP != null && !xRealIP.isEmpty()) {
            return xRealIP;
        }
        
        return request.getRemoteAddr();
    }
    
    private void sendJsonResponse(HttpServletResponse response, Object data) throws IOException {
        response.setContentType("application/json; charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        
        PrintWriter out = response.getWriter();
        out.print(gson.toJson(data));
        out.flush();
    }
    
    private void sendErrorResponse(HttpServletResponse response, String message) throws IOException {
        Map<String, Object> result = new HashMap<>();
        result.put("success", false);
        result.put("message", message);
        sendJsonResponse(response, result);
    }
}